import axios from "axios";
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from "axios";
import router from "@/router";
import { useAuthStore } from "@/store/auth";
import {
  ErrorType,
  DEFAULT_HTTP_ERROR_MESSAGES,
  type ApiError,
  type ErrorHandler,
  type HttpErrorMessages,
} from "./configTypes";
import { message } from "ant-design-vue";

/**
 * 标准响应格式，这里的结构应该与后端返回保持一致，即res.data.data的数据结构
 */
export interface ApiResponse<T = unknown> {
  [key: string]: unknown;
  code?: number;
  status?: number | string;
  success?: boolean;
  data?: T;
  result?: T;
  message: string;
}

// 响应适配器配置
export interface ResponseAdapterConfig {
  /**
   * 检查响应是否成功的函数
   * @param response - Axios响应对象
   * @returns 是否成功
   */
  isSuccess: (response: AxiosResponse<ApiResponse>) => boolean;

  /**
   * 从响应中提取错误消息的函数
   * @param response - Axios响应对象
   * @returns 错误消息
   */
  extractErrorMessage: (response: AxiosResponse<ApiResponse>) => string;

  /**
   * 从响应中提取业务错误码的函数
   * @param response - Axios响应对象
   * @returns 错误码
   */
  extractErrorCode?: (response: AxiosResponse<ApiResponse>) => number | string;
}

class HttpService {
  // axios实例
  private instance: AxiosInstance;
  /**
   * 错误处理函数，这里会对接口错误做全局统一处理，
   *
   * 如果想自定义错误处理函数，通过 setErrorHandler 覆盖即可。
   */
  private errorHandler: ErrorHandler;
  /**
   * HTTP错误消息列表
   *
   * 如果想自定义错误类型，通过 updateHttpErrorMessages 添加新类型即可。
   */
  private httpErrorMessages: HttpErrorMessages;
  /**
   * 响应适配器配置
   */
  private responseAdapter: ResponseAdapterConfig;

  private readonly baseConfig: AxiosRequestConfig = {
    // baseURL: import.meta.env.VITE_API_BASE_URL as string,
    baseURL: "/",
    timeout: 10000,
    headers: {
      "Content-Type": "application/json",
    },
  };

  constructor(
    config: AxiosRequestConfig = {},
    httpErrorMessages: HttpErrorMessages = DEFAULT_HTTP_ERROR_MESSAGES,
    errorHandler?: ErrorHandler,
    responseAdapter?: ResponseAdapterConfig
  ) {
    this.instance = axios.create({
      ...this.baseConfig,
      ...config,
    });

    this.httpErrorMessages = httpErrorMessages;
    this.errorHandler = errorHandler || this.defaultErrorHandler;

    // 设置默认响应适配器
    this.responseAdapter = responseAdapter || this.createDefaultAdapter();
    this.initInterceptors();
  }

  // 创建默认响应适配器
  private createDefaultAdapter(): ResponseAdapterConfig {
    return {
      isSuccess: response => {
        const data = response.data;
        // 多种可能的成功标识
        return (
          data.success === true ||
          data.code === 0 ||
          data.code === 200 ||
          data.status === "success" ||
          (response.status >= 200 && response.status < 300)
        );
      },

      extractErrorMessage: response => {
        const data = response.data;
        // 尝试从常见字段中提取错误消息
        return data.message ?? data.error ?? data.msg ?? "业务错误";
      },

      extractErrorCode: response => {
        const data = response.data;
        return data.code ?? data.status ?? response.status;
      },
    };
  }

  // 默认错误处理函数
  private defaultErrorHandler(error: ApiError) {
    // 记录错误到分析系统
    this.logErrorToAnalytics(error);

    // 根据错误类型显示不同的消息
    switch (error.type) {
      case ErrorType.NETWORK_ERROR:
        message.error("网络连接异常，请检查网络设置");
        break;
      case ErrorType.AUTH_ERROR:
        message.error("登录已过期，请重新登录");
        break;
      case ErrorType.PERMISSION_ERROR:
        message.error("您没有权限执行此操作");
        break;
      case ErrorType.HTTP_ERROR:
        message.error(error.message);
        break;
      case ErrorType.BUSINESS_ERROR:
        message.error(`业务错误: ${error.message}`);
        break;
      case ErrorType.RESPONSE_PARSING_ERROR:
        message.error("服务器返回格式异常");
        console.error("响应解析错误:", error.response?.data);
        break;
      default:
        message.error(`请求失败: ${error.message}`);
    }
  }

  // 记录错误到分析系统
  private logErrorToAnalytics(error: ApiError) {
    // 实际项目中可替换为Sentry、LogRocket等
    console.error(`[HTTP Error] ${error.type}: ${error.message}`, {
      code: error.code,
      url: error.config?.url,
      method: error.config?.method,
      status: error.response?.status,
    });
  }

  // 创建错误对象
  private createError(
    type: ErrorType,
    message: string,
    code?: number | string,
    response?: AxiosResponse,
    config?: AxiosRequestConfig
  ): ApiError {
    const error: ApiError = { type, message, code, response, config };

    // 调用错误处理器
    this.errorHandler(error);

    return error;
  }

  // 初始化拦截器
  private initInterceptors() {
    // 请求拦截器
    this.instance.interceptors.request.use(
      config => {
        const authStore = useAuthStore();
        // 添加认证头
        if (authStore.userToken) {
          config.headers.Authorization = `Bearer ${authStore.userToken}`;
        }

        // 添加自定义头
        // config.headers["X-Client-Id"] = "web-app";

        return config;
      },
      (error: AxiosError) => {
        return Promise.reject(
          this.createError(ErrorType.NETWORK_ERROR, "网络请求配置错误", undefined, undefined, error.config)
        );
      }
    );

    // 响应拦截器
    this.instance.interceptors.response.use(
      (response: AxiosResponse) => {
        // 使用响应适配器判断是否成功
        if (this.responseAdapter.isSuccess(response)) {
          // 提取数据
          return response.data;
        }

        // 业务错误 - 提取错误信息
        const errorMessage = this.responseAdapter.extractErrorMessage(response);
        const errorCode = this.responseAdapter.extractErrorCode?.(response);

        return Promise.reject(this.createError(ErrorType.BUSINESS_ERROR, errorMessage, errorCode, response));
      },
      (error: AxiosError) => {
        // 网络错误
        if (!error.response) {
          return Promise.reject(
            this.createError(
              ErrorType.NETWORK_ERROR,
              "网络连接异常，请检查网络设置",
              undefined,
              undefined,
              error.config
            )
          );
        }

        const response = error.response as AxiosResponse;
        const status = response.status;
        const config = error.config;

        // 认证错误处理
        if (status === 401) {
          const authStore = useAuthStore();
          authStore.clearToken();

          // 重定向到登录页
          const redirect = encodeURIComponent(router.currentRoute.value.fullPath);
          router.push(`/login?redirect=${redirect}`);

          return Promise.reject(
            this.createError(ErrorType.AUTH_ERROR, "登录已过期，请重新登录", status, response, config)
          );
        }

        // 权限错误处理
        if (status === 403) {
          return Promise.reject(
            this.createError(ErrorType.PERMISSION_ERROR, "您没有权限执行此操作", status, response, config)
          );
        }

        // 其他HTTP错误 - 使用配置的错误消息
        const message = this.httpErrorMessages[status] || `请求失败，状态码：${status}`;
        return Promise.reject(this.createError(ErrorType.HTTP_ERROR, message, status, response, config));
      }
    );
  }

  // 设置自定义响应适配器
  public setResponseAdapter(adapter: ResponseAdapterConfig) {
    this.responseAdapter = adapter;
  }

  // 设置自定义错误处理函数
  public setErrorHandler(handler: ErrorHandler) {
    this.errorHandler = handler;
  }

  // 更新HTTP错误消息映射
  public updateHttpErrorMessages(messages: HttpErrorMessages) {
    this.httpErrorMessages = { ...this.httpErrorMessages, ...messages };
  }

  // 公共请求方法
  public request<T = unknown>(config: AxiosRequestConfig): Promise<T> {
    return this.instance.request(config);
  }

  // GET请求
  public get<T = unknown, P = unknown>(
    url: string,
    params?: P,
    config?: Omit<AxiosRequestConfig, "params" | "url" | "method">
  ): Promise<T> {
    return this.instance.get(url, {
      ...config,
      params,
    });
  }

  // POST请求
  public post<T = unknown, D = unknown>(
    url: string,
    data?: D,
    config?: Omit<AxiosRequestConfig, "data" | "url" | "method">
  ): Promise<T> {
    return this.instance.post(url, data, config);
  }

  // PUT请求
  public put<T = unknown, D = unknown>(
    url: string,
    data?: D,
    config?: Omit<AxiosRequestConfig, "data" | "url" | "method">
  ): Promise<T> {
    return this.instance.put(url, data, config);
  }

  // DELETE请求
  public delete<T = unknown, P = unknown>(
    url: string,
    params?: P,
    config?: Omit<AxiosRequestConfig, "params" | "url" | "method">
  ): Promise<T> {
    return this.instance.delete(url, {
      ...config,
      params,
    });
  }

  // PATCH请求
  public patch<T = unknown, D = unknown>(
    url: string,
    data?: D,
    config?: Omit<AxiosRequestConfig, "data" | "url" | "method">
  ): Promise<T> {
    return this.instance.patch(url, data, config);
  }
}

// 导出单例实例
export const request = new HttpService();
